/**
 * 
 */
package jpb.process;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;

/**
 * Simple {@link Callable} implementation that drains
 * output produced by {@link Process} instance, so that
 * it does not stuck due to full buffer.
 * 
 * @author Dariusz Kordonski
 */
public class ProcessOutputDrainer implements Callable<String> {

    private final Process process;
    private final StringBuilder results = new StringBuilder(); 
    private volatile boolean stop = false;

    public ProcessOutputDrainer(Process process) {
        super();
        this.process = process;
    }
    
    public void stop() {
        stop = true;
    }
    private boolean stopped() {
        return stop;
    }

    @Override
    public String call() throws Exception {
        BufferedReader processOutput = wrapInputStream(process);
        do  {
            checkInterrupted();
            readIfAvailable(processOutput);
        } while (!stopped());
        readWhileAvailable(processOutput);
        return results.toString();
    }

    private void checkInterrupted() throws InterruptedException {
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
    }

    private BufferedReader wrapInputStream(Process process) {
        return new BufferedReader(new InputStreamReader(process.getInputStream()));
    }
    
    private void readIfAvailable(BufferedReader processOutput) throws IOException {
        if (processOutput.ready()) {
            results.append(processOutput.readLine()).append("\n");
        }
    }
    private void readWhileAvailable(BufferedReader processOutput) throws IOException {
        while (processOutput.ready()) {
            results.append(processOutput.readLine()).append("\n");
        }
    }
    
}
